package com.qishenyuan.competition.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qishenyuan.competition.common.PageUtil;
import com.qishenyuan.competition.constant.UserConstant;
import com.qishenyuan.competition.dao.UserDao;
import com.qishenyuan.competition.dto.FindJobBriefReq;
import com.qishenyuan.competition.dto.FindJobTopicReq;
import com.qishenyuan.competition.exception.BusinessErrorType;
import com.qishenyuan.competition.exception.BusinessException;
import com.qishenyuan.competition.model.FindJob;
import com.qishenyuan.competition.dao.FindJobDao;
import com.qishenyuan.competition.model.User;
import com.qishenyuan.competition.service.FindJobService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qishenyuan.competition.utils.AliOssUtil;
import com.qishenyuan.competition.vo.FindJobBriefResp;
import com.qishenyuan.competition.vo.FindJobResp;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.qishenyuan.competition.vo.FindJobBriefResp.buildVo;

/**
 * <p>
 * 找工作帖子信息表 服务实现类
 * </p>
 *
 * @author qishenyuan
 * @since 2025-03-25
 */
@Service
@Slf4j
public class FindJobServiceImpl extends ServiceImpl<FindJobDao, FindJob> implements FindJobService {

    @Autowired
    private UserDao userDao;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public IPage<FindJobBriefResp> getFindJobList(FindJobBriefReq findJobBriefReq) {
        IPage<FindJob> iPage = PageUtil.toIPage(findJobBriefReq.getPageQuery());
        QueryWrapper<FindJob>  queryWrapper = new QueryWrapper<>();
        if(findJobBriefReq.getTag() != null){
            queryWrapper.eq("tag",findJobBriefReq.getTag());
        }
        if(findJobBriefReq.getType() != null){
            queryWrapper.eq("type",findJobBriefReq.getType());
        }
        queryWrapper.orderByDesc("create_time");
        IPage<FindJob> iPageResult = baseMapper.selectPage(iPage,queryWrapper);
        if(Objects.isNull(iPageResult.getRecords())||iPageResult.getRecords().isEmpty()){
            return iPageResult.convert(findJob -> buildVo(findJob,null));
        }

        List<String> uids = iPageResult.getRecords().stream().map(FindJob::getUid).collect(Collectors.toList());
        List<User> users = userDao.listByUids(uids);

        // key->uid, value->User
        Map<String, User> userMap = users.stream()
                .collect(Collectors.toMap(User::getUid, u -> u, (u1, u2) -> u1));
        return iPageResult.convert(findJob -> {
            User user = userMap.get(findJob.getUid());
            return buildVo(findJob, user);
        });
    }

    @Override
    public FindJobResp getFindJob(Integer id) {
        FindJob findJob = baseMapper.selectById(id);
        if(findJob == null){
            return null;
        }
        FindJobResp resp = FindJobResp.buildVo(findJob);
        User user = userDao.selectByUid(findJob.getUid());
        resp.setUserName(user.getNickName());
        if (UserConstant.DEFAULT_AVATAR.equals(user.getAvatar())) {
            resp.setAvatar(UserConstant.DEFAULT_AVATAR);
        }else {
            resp.setAvatar(AliOssUtil.generatePreSignedUrl(user.getAvatar()));
        }
        resp.setSchool(user.getSchool());
        return resp;
    }

    @Override
    public void createFindJobTopic(String token, FindJobTopicReq findJobTopicReq) {
        if(StringUtils.isBlank(token)){
            throw new BusinessException(BusinessErrorType.INVALID_USER_TOKEN);
        }
        String userStr = stringRedisTemplate.opsForValue().get(token);
        if (StringUtils.isBlank(userStr)) {
            throw new BusinessException(BusinessErrorType.INVALID_USER_TOKEN);
        }
        try{
            User user = objectMapper.readValue(userStr, User.class);
            String uidFromRedis = user.getUid();
            if (!findJobTopicReq.getUid().equals(uidFromRedis)||findJobTopicReq.getUid().equals(UserConstant.DEFAULT_UID)){
                throw new BusinessException(BusinessErrorType.INVALID_USER_TOKEN);
            }
            FindJob findJob = FindJob.buildModel(findJobTopicReq);
            int insert = baseMapper.insert(findJob);
            if(insert != 1){
                throw new BusinessException(BusinessErrorType.CREATE_TOPIC_FAILED);
            }
        }catch (Exception e){
            if (e instanceof BusinessException) {
                throw (BusinessException) e;
            }
            log.error("check user token error, 【token】: {}", token, e);
            throw new BusinessException(BusinessErrorType.SYSTEM_ERROR);
        }
    }

    @Override
    public List<FindJobBriefResp> searchFindJob(String key) {
        QueryWrapper<FindJob> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(key),"title",key);
        List<FindJob> findJobs = baseMapper.selectList(queryWrapper);
        if(Objects.isNull(findJobs)||findJobs.isEmpty()){
            return findJobs.stream().map(findJob -> buildVo(findJob,null)).collect(Collectors.toList());
        }

        List<String> uids = findJobs.stream().map(FindJob::getUid).collect(Collectors.toList());
        List<User> users = userDao.listByUids(uids);

        // key->uid, value->User
        Map<String, User> userMap = users.stream()
                .collect(Collectors.toMap(User::getUid, u -> u, (u1, u2) -> u1));
        return findJobs.stream().map(findJob -> {
            User user = userMap.get(findJob.getUid());
            return buildVo(findJob, user);
        }).collect(Collectors.toList());
    }
}
